﻿Option Explicit On
Option Strict On

Imports System
Imports System.Runtime.InteropServices
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Xml.Serialization

Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.WebControls
Imports Microsoft.SharePoint.WebPartPages
Imports System.ComponentModel


Namespace MJB.Sharepoint.GoogleMaps

    <Guid("3fe0a0bf-c5d6-4ad0-9eef-6f8fa092a808")> _
    Public Class MapsWebPart
        Inherits Microsoft.SharePoint.WebPartPages.WebPart

        Public Sub New()
        End Sub


        Private Const default_Text As String = ""
        Public strThe_Site As String = default_Text
        Public strThe_List As String = default_Text
        Public strfieldLong As String = default_Text
        Public strfieldLat As String = default_Text
        Public strfieldTitle As String = default_Text
        Public strfieldImage As String = default_Text
        Public strfieldDescription As String = default_Text
        Public strdefaultImageURL As String = default_Text
        Public strAPIKey As String = default_Text
        Public strsingleLat As String = default_Text
        Public strsingleLong As String = default_Text
        Public strsingleTitle As String = default_Text
        Public strsingleImageURL As String = default_Text
        Public strMapCentre As String = default_Text
        Public strZoom As String = default_Text
        Public strMapType As String = default_Text

        Dim strMapCentre_lat As String
        Dim strMapCentre_long As String



        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("The_Site"), Description("Site location where the list is.")> Property the_site() As String
            Get
                Return strThe_Site
            End Get

            Set(ByVal Value As String)
                strThe_Site = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("The_List"), Description("Location of the List.")> Property the_list() As String
            Get
                Return strThe_List
            End Get

            Set(ByVal Value As String)
                strThe_List = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("fieldLong"), Description("Field holding the Long.")> Property fieldLong() As String
            Get
                Return strfieldLong
            End Get

            Set(ByVal Value As String)
                strfieldLong = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("fieldLat"), Description("Field holding the Lat.")> Property fieldLat() As String
            Get
                Return strfieldLat
            End Get

            Set(ByVal Value As String)
                strfieldLat = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("fieldTitle"), Description("Field holding the building title.")> Property fieldTitle() As String
            Get
                Return strfieldTitle
            End Get

            Set(ByVal Value As String)
                strfieldTitle = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("fieldImage"), Description("Image field.")> Property fieldImage() As String
            Get
                Return strfieldImage
            End Get

            Set(ByVal Value As String)
                strfieldImage = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("fieldDescription"), Description("Description field.")> Property fieldDescription() As String
            Get
                Return strfieldDescription
            End Get

            Set(ByVal Value As String)
                strfieldDescription = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("defaultImageURL"), Description("Default Image Location.")> Property defaultImageURL() As String
            Get
                Return strdefaultImageURL
            End Get

            Set(ByVal Value As String)
                strdefaultImageURL = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("APIKey"), Description("Google Maps API Key.")> Property APIKey() As String
            Get
                Return strAPIKey
            End Get

            Set(ByVal Value As String)
                strAPIKey = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("singleLat"), Description("Lat for a single point")> Property singleLat() As String
            Get
                Return strsingleLat
            End Get

            Set(ByVal Value As String)
                strsingleLat = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("singleLong"), Description("Long for a single point.")> Property singleLong() As String
            Get
                Return strsingleLong
            End Get

            Set(ByVal Value As String)
                strsingleLong = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("singleTitle"), Description("Single Point title.")> Property singleTitle() As String
            Get
                Return strsingleTitle
            End Get

            Set(ByVal Value As String)
                strsingleTitle = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("singleImageURL"), Description("Location of the image for a single point.")> Property singleImageURL() As String
            Get
                Return strsingleImageURL
            End Get

            Set(ByVal Value As String)
                strsingleImageURL = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("MapCentre"), Description("If a list is used, this has the centre point in it.")> Property MapCentre() As String
            Get
                Return strMapCentre
            End Get

            Set(ByVal Value As String)
                strMapCentre = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("Zoom"), Description("Holds the Zoom level.")> Property Zoom() As String
            Get
                Return strZoom
            End Get

            Set(ByVal Value As String)
                strZoom = Value
            End Set
        End Property

        <Bindable(True), Browsable(False), Category("Text"), DefaultValue(default_Text), WebPartStorage(Storage.Shared), FriendlyName("MapType"), Description("Holds the type of map, hybrid, normal or satellite.")> Property MapType() As String
            Get
                Return strMapType
            End Get

            Set(ByVal Value As String)
                strMapType = Value
            End Set
        End Property

        Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
            MapScript()
            MyBase.OnPreRender(e)
        End Sub

        Protected Sub getMapCentre()

            If isListUsed() Then

                Dim site As SPWeb = Microsoft.SharePoint.WebControls.SPControl.GetContextSite(Context).OpenWeb(the_site)
                Dim list As SPList = site.Lists(the_list)
                Dim listItems As SPListItemCollection
                Dim strQ As String
                Dim q As New SPQuery

                strQ = "<Where><Eq><FieldRef Name=""ID"" /><Value Type=""Counter"">" & MapCentre & "</Value></Eq></Where>"

                q.Query = strQ

                listItems = list.GetItems(q)

                strMapCentre_lat = listItems(0).Item(fieldLat).ToString
                strMapCentre_long = listItems(0).Item(fieldLong).ToString

            Else

                strMapCentre_lat = singleLat
                strMapCentre_long = singleLong

            End If


        End Sub

        Dim code As SPSecurity.CodeToRunElevated


        Private Function MapScript() As String



            Dim script As New System.Text.StringBuilder

            script.Append("<script type=""text/javascript"" language=""javascript"" src=""http://maps.google.com/maps?file=api&amp;v=2&amp;key=" & APIKey & """></script>" & Environment.NewLine & Environment.NewLine)

            script.Append("<script language=""javascript"" type=""text/javascript"">" & Environment.NewLine & Environment.NewLine)
            script.Append("//<![CDATA[" & Environment.NewLine & Environment.NewLine)
            script.Append("if (GBrowserIsCompatible()) {" & Environment.NewLine)
            script.Append("var side_bar_html = """";" & Environment.NewLine)
            script.Append("var gmarkers = [];" & Environment.NewLine)
            script.Append("var htmls = [];" & Environment.NewLine)
            script.Append("var to_htmls = [];" & Environment.NewLine)
            script.Append("var from_htmls = [];" & Environment.NewLine)
            script.Append("var i=0;" & Environment.NewLine)
            script.Append("function createMarker(point,name,html) {" & Environment.NewLine)
            script.Append("var marker = new GMarker(point);" & Environment.NewLine)

            'Creates an informaion bubble that pops up if you want to find directions to this
            'point to somewhere else

            script.Append("to_htmls[i] = html + '<br/> Directions: ")
            script.Append("<strong>To Here</strong> - <A href=""javascript:fromhere(' + i + ')"">From Here</a><br/>")
            script.Append(" Address: <br/>")

            If isListUsed() Then
                script.Append("One of our sites<br/>")
                script.Append(createDDL())
                script.Append(" OR </br>")
            End If

            script.Append("Enter an address: <br/>")
            script.Append("<input type=""text"" size=""20"" maxlength=""40"" id=""saddr"" name=""saddr"" value="""" />")
            script.Append("<input value=""Get Directions"" type=""Button"" onclick=""javascript:getDirections();"" />")
            script.Append("<input type=""hidden"" name=""daddr"" value=""' + name+ ""@"" + point.lat() + ',' + point.lng() + '"" />';" & Environment.NewLine)

            'Creates an informaion bubble that pops up if you want to find directions from this
            'point to somewhere else

            script.Append("from_htmls[i] = html + '<br/> Directions: ")
            script.Append("<A href=""javascript:tohere(' + i + ')"">To Here</a> - <strong>From Here</strong><br/>")
            script.Append(" Address: <br/>")

            If isListUsed() Then
                script.Append("One of our sites<br/>")
                script.Append(createDDL())
                script.Append(" OR </br>")
            End If

            script.Append("Enter an address: <br/>")
            script.Append("<input type=""text"" size=""20"" maxlength=""40"" id=""daddr"" name=""daddr"" value="""" />")
            script.Append("<input value=""Get Directions"" type=""Button"" onclick=""javascript:getDirections();""/>")
            script.Append("<input type=""hidden"" name=""saddr"" value=""' + name + ""@"" + point.lat() + ',' + point.lng() + '"" />';" & Environment.NewLine)

            'Creates the default information bubble text showing a pop up for directions

            script.Append("html = html + '<br />Directions: <a href=""javascript:tohere(' + i + ')"">To Here</a> - <a href=""javascript:fromhere(' + i + ')"">From Here</a>';" & Environment.NewLine & Environment.NewLine)


            script.Append("GEvent.addListener(marker, ""click"", function() {" & Environment.NewLine)
            script.Append("marker.openInfoWindowHtml(html);" & Environment.NewLine)
            script.Append("});" & Environment.NewLine)


            script.Append("gmarkers[i] = marker;" & Environment.NewLine)
            script.Append("htmls[i] = html;" & Environment.NewLine)

            script.Append("side_bar_html += '<a href=""javascript:myclick(' + i + ')"">' + name + '</a><br>';")


            script.Append("i++;" & Environment.NewLine)
            script.Append("return marker;}" & Environment.NewLine & Environment.NewLine)

            'functions to open the different information bubbles

            script.Append("function myclick(i){GEvent.trigger(gmarkers[i],""click"");}" & Environment.NewLine)
            script.Append("function tohere(i){gmarkers[i].openInfoWindowHtml(to_htmls[i]);}" & Environment.NewLine)
            script.Append("function fromhere(i){gmarkers[i].openInfoWindowHtml(from_htmls[i]);}" & Environment.NewLine & Environment.NewLine)


            script.Append("function getDirections() {" & Environment.NewLine)
            script.Append("var saddr = document.getElementById(""saddr"").value;" & Environment.NewLine)
            script.Append("var daddr = document.getElementById(""daddr"").value;" & Environment.NewLine)

            If isListUsed() Then
                script.Append("var ddlSites = document.getElementById(""ddlSites"").value;" & Environment.NewLine)
                script.Append("if (ddlSites=="""") {" & Environment.NewLine)
                script.Append("gdir.load('from: ' + saddr + ' to: ' + daddr);" & Environment.NewLine)
                script.Append("}else if (daddr==""""){ " & Environment.NewLine)
                script.Append("gdir.load('from: ' + saddr + ' to: ' + ddlSites);" & Environment.NewLine)
                script.Append("}else { " & Environment.NewLine)
                script.Append("gdir.load('from: ' + ddlSites + ' to: ' + daddr);" & Environment.NewLine)
                script.Append("}" & Environment.NewLine)
            Else
                script.Append("gdir.load('from: ' + saddr + ' to: ' + daddr);" & Environment.NewLine)
            End If
            script.Append("}" & Environment.NewLine)



            'Gets and sets the centre of the map

            getMapCentre()

            script.Append("var map = new GMap2(document.getElementById(""map""));" & Environment.NewLine)
            script.Append("map.addControl(new GLargeMapControl());" & Environment.NewLine)
            script.Append("map.addControl(new GMapTypeControl());" & Environment.NewLine)
            script.Append("map.setMapType(" & MapType & ");" & Environment.NewLine)
            script.Append("map.setCenter(new GLatLng(" & strMapCentre_lat & "," & strMapCentre_long & ")," & Zoom & ");" & Environment.NewLine)

            script.Append("var gdir=new GDirections(map, document.getElementById(""directions""));" & Environment.NewLine & Environment.NewLine)


            Dim pre_click As String = ""
            Dim pre_click_counter As Integer = 0
            Dim image As String = ""


            If isListUsed() Then

                Dim web As SPWeb = Microsoft.SharePoint.WebControls.SPControl.GetContextSite(Context).OpenWeb(the_site)
                Dim list As SPList = web.Lists(the_list)
                Dim listItems As SPListItemCollection
                Dim listItem As SPListItem
                Dim q As New SPQuery
                Dim desc As String
                Dim strQ As String

                strQ = "<OrderBy><FieldRef Name=""" & fieldTitle & """ /></OrderBy>"
                q.Query = strQ

                listItems = list.GetItems(q)

                For Each listItem In listItems

                    If String.IsNullOrEmpty(fieldImage) Then
                        If String.IsNullOrEmpty(defaultImageURL) Then
                            image = ""
                        Else
                            image = "<img src='" & defaultImageURL & "' alt='Image representing " & listItem(fieldTitle).ToString & "' />"
                        End If
                    ElseIf listItem(fieldImage) Is Nothing Then
                        If String.IsNullOrEmpty(defaultImageURL) Then
                            image = ""
                        Else
                            image = "<img src='" & defaultImageURL & "' alt='Image representing " & listItem(fieldTitle).ToString & "' />"
                        End If
                    Else
                        image = "<img src='" & listItem(fieldImage).ToString & "' alt='Image representing " & listItem(fieldTitle).ToString & "' />"
                    End If

                    If Not String.IsNullOrEmpty(fieldDescription) Then
                        desc = "<tr><td colspan='2'>" & removeformatting(listItem(fieldDescription).ToString) & "</td></tr>"
                    End If


                    script.Append("var point = new GLatLng(" & listItem(fieldLat).ToString & "," & listItem(fieldLong).ToString & ");" & Environment.NewLine)
                    script.Append("var marker = createMarker(point, """ & listItem(fieldTitle).ToString & """,""<table width='200px'><tr><td>" & image & "</td><td><strong>" & listItem(fieldTitle).ToString & "</td></tr>" & desc & "</table>"");" & Environment.NewLine)
                    script.Append("map.addOverlay(marker);" & Environment.NewLine & Environment.NewLine)

                    If listItem("ows_ID").ToString = MapCentre Then
                        pre_click = "setTimeout('myclick(" & pre_click_counter & ")','1000');"
                    End If

                    pre_click_counter = pre_click_counter + 1

                Next

            Else

                If String.IsNullOrEmpty(singleImageURL) Then
                    image = ""
                Else
                    image = "<img src='" & singleImageURL & "' alt='Image representing " & singleTitle & "' />"
                End If


                script.Append("var point = new GLatLng(" & singleLat & "," & singleLong & ");" & Environment.NewLine)
                script.Append("var marker = createMarker(point, """ & singleTitle & """,""<table width='200px'><tr><td>" & image & "</td><td><strong>" & singleTitle & "</td></tr></table>"");" & Environment.NewLine)
                script.Append("map.addOverlay(marker);" & Environment.NewLine & Environment.NewLine)


                pre_click = "setTimeout('myclick(0)','1000');"

            End If


            script.Append("document.getElementById(""side_bar"").innerHTML = side_bar_html;" & Environment.NewLine)
            script.Append("setTimeout('map.setCenter(new GLatLng(" & strMapCentre_lat & "," & strMapCentre_long & ")," & Zoom & ")','750');" & Environment.NewLine)
            script.Append("setTimeout('map.checkResize()','500');" & Environment.NewLine)
            script.Append(pre_click & Environment.NewLine & Environment.NewLine)
            script.Append("}" & Environment.NewLine & "//]]>" & Environment.NewLine)
            script.Append("</script>" & Environment.NewLine)

            'Me.Page.ClientScript.RegisterClientScriptBlock(GetType(Page), "MapScript", script.ToString)

            Return script.ToString

        End Function

        Function removeformatting(ByVal htmlstring As String) As String

            htmlstring = htmlstring.Replace(Microsoft.VisualBasic.Constants.vbCrLf, "")
            htmlstring = htmlstring.Replace("""", "'")
            Return htmlstring

        End Function

        Function createDDL() As String
            Dim strSites As New Text.StringBuilder
            Dim web As SPWeb = Microsoft.SharePoint.WebControls.SPControl.GetContextSite(Context).OpenWeb(the_site)
            Dim list As SPList = web.Lists(the_list)
            Dim listItems As SPListItemCollection
            Dim listItem As SPListItem
            Dim q As New SPQuery
            Dim strQ As String

            strQ = "<OrderBy><FieldRef Name=""" & fieldTitle & """ /></OrderBy>"

            q.Query = strQ

            listItems = list.GetItems(q)

            strSites.Append("<select id=""ddlSites"" name=""ddlSites"">")

            strSites.Append("<option value="""">Pick one</option>")

            For Each listItem In listItems

                strSites.Append("<option value=""" & listItem(fieldTitle).ToString & "@" & listItem(fieldLat).ToString & "," & listItem(fieldLong).ToString & """>" & listItem(fieldTitle).ToString & "</option>")

            Next


            strSites.Append("</select>")


            Return strSites.ToString
        End Function

        Function isListUsed() As Boolean
            If String.IsNullOrEmpty(the_list) Or String.IsNullOrEmpty(the_site) Then
                Return False
            Else
                Return True
            End If
        End Function

        Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)

            Dim ColourLink As New HtmlControls.HtmlGenericControl
            ColourLink.Attributes.Add("type", "text/css")
            ColourLink.Attributes.Add("rel", "stylesheet")
            ColourLink.Attributes.Add("href", "/Style Library/mapswebpart.css")
            ColourLink.TagName = "link"
            ColourLink.RenderControl(writer)


            writer.WriteBeginTag("div")
            writer.WriteAttribute("ID", "map")
            writer.Write(Html32TextWriter.TagRightChar)

            writer.WriteEndTag("div")


            writer.WriteBeginTag("div")
            writer.WriteAttribute("ID", "side_bar")
            writer.Write(Html32TextWriter.TagRightChar)

            writer.WriteEndTag("div")

            writer.WriteBeginTag("div")
            writer.WriteAttribute("ID", "directions")
            writer.Write(Html32TextWriter.TagRightChar)

            writer.WriteEndTag("div")

            writer.Write(MapScript())

            MyBase.Render(writer)
        End Sub

        Public Overrides Function GetToolParts() As ToolPart()
            Dim toolParts(2) As ToolPart
            Dim wptp As WebPartToolPart = New WebPartToolPart
            Dim custom As CustomPropertyToolPart = New CustomPropertyToolPart
            toolParts(0) = wptp
            toolParts(1) = New MapsToolPart
            Return toolParts
        End Function

        Protected Overrides Sub CreateChildControls()
            MyBase.CreateChildControls()



        End Sub

    End Class

End Namespace
